/**
 * 项目名：五位一体化工安全信息平台
 * 日期：    2019-11-24 23:34:51
 * Copyright (c) 2015- joysuch-版权所有
 */

package com.joysuch.wwyt.bp.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.joysuch.wwyt.api.base.dto.ApiDepartDto;
import com.joysuch.wwyt.api.basedata.service.BpDepartSyncService;
import com.joysuch.wwyt.bp.bean.*;
import com.joysuch.wwyt.bp.bean.BpDepartBean.SearchDepartBean;
import com.joysuch.wwyt.bp.entity.BpDepart;
import com.joysuch.wwyt.bp.entity.BpJob;
import com.joysuch.wwyt.bp.entity.dsl.QBpDepart;
import com.joysuch.wwyt.bp.entity.investigate.BpInvestigatePlan;
import com.joysuch.wwyt.bp.enums.DataStateTypes;
import com.joysuch.wwyt.bp.enums.DepartType;
import com.joysuch.wwyt.bp.repository.BpDepartDao;
import com.joysuch.wwyt.bp.repository.BpInvestigatePlanRepository;
import com.joysuch.wwyt.bp.repository.BpJobDao;
import com.joysuch.wwyt.bp.service.BpDepartService;
import com.joysuch.wwyt.core.bean.BaseDepartDutyUserBean;
import com.joysuch.wwyt.core.bean.SimpleInfoBean;
import com.joysuch.wwyt.core.bean.SimpleSelectListBean;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.util.JsonUtil;
import com.joysuch.wwyt.core.common.util.PageDataUtils;
import com.joysuch.wwyt.core.common.util.PageDataUtils.PageDataConvert;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.exception.ApiBusinessException;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.service.BaseConfigService;
import com.joysuch.wwyt.core.service.BaseRoleDataAuthService;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.dzhapi.bean.ApiBaseUserBean;
import com.joysuch.wwyt.dzhapi.bean.ApiBpDepartBean;
import com.joysuch.wwyt.dzhapi.dto.BuildDataDto;
import com.joysuch.wwyt.dzhapi.mapper.ApiBaseUserMapper;
import com.joysuch.wwyt.dzhapi.mapper.ApiBpDepartMapper;
import com.joysuch.wwyt.risk.entity.RiskPointEvaluationDetail;
import com.joysuch.wwyt.risk.entity.vo.DepartDeleteCheckVO;
import com.joysuch.wwyt.risk.entity.vo.RiskPointDeleteCheckVO;
import com.joysuch.wwyt.risk.repository.RiskDistrictDao;
import com.joysuch.wwyt.risk.repository.RiskPointEvaluationBusinessDao;
import com.joysuch.wwyt.risk.repository.RiskPointEvaluationDetailDao;
import com.joysuch.wwyt.util.SnowFlakeUtil;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.util.Assert;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class BpDepartServiceImpl implements BpDepartService {
    @Autowired
    private BpDepartDao dao;
    @Autowired
    private EntityManager entityManager;
    @Autowired
    private BaseUserDao baseUserDao;
    @Autowired
    private BpJobDao jobDao;

    @Autowired
    private BpDepartSyncService departSyncService;
    @Autowired
    private BaseRoleDataAuthService dataAuthService;
    @Autowired
    private BaseConfigService baseConfigService;
    @Autowired
    private ApiBaseUserMapper userMapper;
    @Autowired
    private ApiBpDepartMapper departMapper;
    @Autowired
    private RiskDistrictDao riskDistrictDao;
    @Autowired
    private BpInvestigatePlanRepository bpInvestigatePlanRepository;
    @Autowired
    private RiskPointEvaluationDetailDao riskPointEvaluationDetailDao;


    @Override
    public void add(BpDepart entity) {
        BpDepart parent = null;
        if (entity.getParentId() != null) {
            parent = dao.getOne(entity.getParentId());
        } else {
            parent = dao.findFirstByCode(Context.getCompanyCode());
        }
        if (parent != null) {
            // 锁定父部门，防止并发修改，导致childNo出错
            entityManager.lock(parent, LockModeType.PESSIMISTIC_WRITE);
            //部门名称不能重复
            List<BpDepart> parentList = dao.findByParentId(parent.getId());
            for (BpDepart bpDepart : parentList) {
                if (entity.getName().equals(bpDepart.getName())) {
                    throw new IllegalArgumentException("此部门名已存在");
                }
            }
        }
        Integer no = parent.getChildNo();
        if (no == null) {
            no = 1;
        }
        entity.setChildNo(1);
        if (entity.getType() == null) {
            entity.setType(DepartType.DEPART.getId());
        }
        entity.setCode(parent.getCode() + "-" + StringUtils.leftPad(no + "", 3, '0'));
        entity.setUniqueId(SnowFlakeUtil.getDepartId());

        if (parent.getUniqueId() == null) {
            parent.setUniqueId(SnowFlakeUtil.getDepartId());
        }
        entity.setOrgCode(Context.getCompanyCode());
        entity.setTenentId(Context.getCurrentTenantId());
        // 调用同步接口，同步部门信息到人员在岗在位
        boolean sync = departSyncService.syncDepart(entity, parent);
        if (sync) {
            entity.setLocateSync(true);
        } else {
            entity.setLocateSync(false);
        }
        BpDepart save = dao.save(entity);
        checkDepartCode(save);
        parent.setChildNo(no + 1);
        dao.save(parent);
        dataAuthService.initTenantRoleDepartCache();
    }

    @Override
    public void update(BpDepart entity) {
        BpDepart content = dao.findById(entity.getId()).get();
        entityManager.lock(content, LockModeType.PESSIMISTIC_WRITE);
        content.setChiefId(entity.getChiefId());
        content.setName(entity.getName());
        content.setRemark(entity.getRemark());
        // content.setParentId(null);
        // TODO set nessessary properties
        if (content.getUniqueId() == null) {
            content.setUniqueId(SnowFlakeUtil.getDepartId());
        }
        content.setType(entity.getType());
        // 调用同步接口，同步部门信息到人员在岗在位
        BpDepart parent = dao.findById(content.getParentId()).get();
        List<BpDepart> bpDepartList = dao.findByNameAndParentIdAndIdNotEq(entity.getName(), parent.getId(), entity.getId());
        if (!CollectionUtils.isEmpty(bpDepartList)) {
            throw new IllegalArgumentException("部门名称已存在");
        }
        boolean sync = departSyncService.syncDepart(content, parent);
        if (sync) {
            content.setLocateSync(true);
        } else {
            content.setLocateSync(false);
        }
        BpDepart save = dao.save(content);
        checkDepartCode(save);
    }

    private void checkDepartCode(BpDepart depart) {
        int count = dao.countByCodeAndState(depart.getCode());
        if (count > 1) {
            throw new IllegalArgumentException("该部门编码已存在");
        }
    }

    @Override
    public BpDepartBean findByPage(Pageable page) {
        List<BpDepart> all = dao.findAll();
        ArrayList<BpDepartBean> list = new ArrayList<>();
        Map<Long, BpDepartBean> map = new HashMap<>();
        for (BpDepart d : all) {
            BpDepartBean bpDepartBean = new BpDepartBean();
            if (d.getShowState() == null || d.getShowState() != 44) {
                bpDepartBean.setId(d.getId());
                bpDepartBean.setLabel(d.getName());
                bpDepartBean.setIcon("el-icon-s-home");
                bpDepartBean.setParentId(d.getParentId());
                bpDepartBean.setType(d.getType());
                if (d.getParentId() != null) {
                    bpDepartBean.setParentName(dao.findDepartNameById(d.getParentId()));
                }
                map.put(d.getId(), bpDepartBean);
                list.add(bpDepartBean);
            }
        }
        for (BpDepartBean d : list) {
            BpDepartBean parent = map.get(d.getParentId());
            if (parent != null) {
                parent.getChildren().add(d);
            }
        }

        return list.size() > 0 ? findTop(list.get(0), map) : null;
        // return null;
    }

    private Predicate prepareSearchConditon(SearchDepartBean condition, List<Long> deptIds) {
        QBpDepart q = QBpDepart.bpDepart1;
        Predicate predicate = q.isNotNull();
        predicate = ExpressionUtils.and(predicate,
                ExpressionUtils.or(q.showState.notIn(DataStateTypes.DELETE.getState()),
                        q.showState.isNull()));
        if (condition.getNameOrCode() != null) {
            predicate = ExpressionUtils.and(predicate, ExpressionUtils.or(q.name.contains(condition.getNameOrCode()),
                    q.code.like("%" + condition.getNameOrCode() + "%")));
        }
        if (condition.getType() != null) {
            predicate = ExpressionUtils.and(predicate, q.type.eq(condition.getType()));
        }
        if (!CollectionUtils.isEmpty(deptIds)) {
            predicate = ExpressionUtils.and(predicate, q.id.in(deptIds));
        }
        return predicate;
    }

    private BpDepartBean findTop(BpDepartBean bpDepartBean, Map<Long, BpDepartBean> map) {
        while (bpDepartBean.getParentId() != null) {
            bpDepartBean = map.get(bpDepartBean.getParentId());
        }
        return bpDepartBean;
    }

    @Override
    public void delete(Long id) throws ApiBusinessException {
        //判断部门下是否有 人员/子部门、是否有关联的未删除的风险对象、日常隐患排查计划、双预防隐患排查计划
        DepartDeleteCheckVO vo = checkDeleteDepart(id);
        // 调用同步接口，同步部门信息到人员在岗在位
        BpDepart depart = dao.findById(id).get();
        if (vo.getTotalNum() > 0) {
            vo.setDepartName(depart.getName());
            throw new ApiBusinessException(Status.DELETE_CHECK_FAILED.getCode(), JSONObject.toJSONString(vo));
        }
        if (depart.getUniqueId() != null && baseConfigService.checkIfSync()) {
            boolean b = departSyncService.deleteSync(depart.getUniqueId());
            depart.setLocateSync(b);
        }
        depart.setShowState(DataStateTypes.DELETE.getState());
        dao.save(depart);
    }

    @Override
    public void apiDelete(Long id, BuildDataDto dto) {
        //判断部门下是否有该人员/子部门
        apiCheckDeleteDepart(id, dto);
        // 调用同步接口，同步部门信息到人员在岗在位
        ApiBpDepartBean departBean = departMapper.selectById(id);
        if (departBean != null && baseConfigService.checkApiIfSync(dto) && departBean.getUniqueId() != null) {
            boolean b = departSyncService.deleteSync(departBean.getUniqueId());
            departBean.setLocateSync(b);
        }
        departBean.setShowState(DataStateTypes.DELETE.getState());
        departMapper.updateById(departBean);
//        dao.save(depart);
    }

    private DepartDeleteCheckVO checkDeleteDepart(Long departId) {
        DepartDeleteCheckVO vo = new DepartDeleteCheckVO();
        List<BaseUser> uList = baseUserDao.findBydepartId(departId);
        // 部门下人员数量
        vo.setPersonNum(CollectionUtils.isEmpty(uList) ? 0 : uList.size());
        BpDepart depart = dao.findById(departId).orElseThrow(() -> new IllegalArgumentException("部门不存在"));
        List<BpDepart> dList = dao.findLikeCode(depart.getCode());
        // 部门下子部门数量
        vo.setChildDepartNum(CollectionUtils.isEmpty(dList) ? 0 : dList.size());
        // 部门关联的风险对象数量
        int riskDistrictNum = riskDistrictDao.countByDepartId(depart.getId());
        vo.setRiskDistrictNum(riskDistrictNum);
        // 部门关联的日常隐患排查计划数量
        List<BpInvestigatePlan> investigatePlans = bpInvestigatePlanRepository.findByDepartId(depart.getId());
        long investigatePlanNum = investigatePlans.stream().filter(item -> {
            String checkDepartJson = item.getCheckDepartJson();
            if (StringUtils.isNotEmpty(checkDepartJson)) {
                List<Long> departIds = JsonUtil.fromListJson(checkDepartJson, Long.class);
                return !CollectionUtils.isEmpty(departIds) && departIds.contains(departId);
            } else {
                return false;
            }
        }).count();
        vo.setInvestigatePlanNum(Long.valueOf(investigatePlanNum).intValue());

        // 部门关联的双预防隐患排查计划数量
        List<RiskPointEvaluationDetail> riskPointEvaluationDetailList = riskPointEvaluationDetailDao.findByDepartId(depart.getId());
        int riskPointControlNum = 0;
        for (RiskPointEvaluationDetail item : riskPointEvaluationDetailList) {
            String responseDepartIds = item.getResponseDepartIds();
            if (StringUtils.isNotEmpty(responseDepartIds)) {
                String[] departIdArr = responseDepartIds.split(",");
                List<String> departIds = Arrays.asList(departIdArr);
                if (departIds.contains(String.valueOf(departId))) {
                    riskPointControlNum += bpInvestigatePlanRepository.countByRiskPointIdAndPointEvaluationId(item.getRiskPointId(), item.getPointEvaluationId());
                }
            }
        }
        vo.setRiskPointControlNum(riskPointControlNum);
        vo.setTotalNum(vo.getRiskDistrictNum() + vo.getInvestigatePlanNum() + vo.getRiskPointControlNum() + vo.getPersonNum() + vo.getChildDepartNum());
        return vo;
    }

    private void apiCheckDeleteDepart(Long departId, BuildDataDto dto) {
        List<ApiBaseUserBean> uList = userMapper.findByDepartId(departId, dto.getTenentId(), dto.getOrgCode());
//        List<BaseUser> uList = baseUserDao.findBydepartId(departId);
        ApiBpDepartBean departBean = departMapper.selectById(departId);
        if (departBean == null) {
            throw new IllegalArgumentException("部门不存在");
        }
//        BpDepart depart = dao.findById(departId).orElseThrow(() -> new IllegalArgumentException("部门不存在"));
        List<ApiBpDepartBean> dList = departMapper.findLikeCode(departBean.getCode(), dto.getTenentId(), dto.getOrgCode());
//        List<BpDepart> dList = dao.findLikeCode(depart.getCode());
        if (!CollectionUtils.isEmpty(uList)) {
            throw new IllegalArgumentException("该部门(" + departBean.getName() + ")存在人员，请先移除人员后再删除部门");
        }
        if (dList.size() > 0) {
            throw new IllegalArgumentException("该部门(" + departBean.getName() + ")存在子部门，请先移除子部门后再删除部门");
        }
    }

    @Override
    public BpDepart findById(Long id) {
        return dao.findById(id).get();
    }

    @Override
    public Page<BpDepartListBean> get(Long id, Pageable page) {
        QBpDepart bpDepart1 = QBpDepart.bpDepart1;
        Predicate predicate = bpDepart1.isNotNull();
        predicate = ExpressionUtils.and(predicate,
                ExpressionUtils.or(bpDepart1.showState.notIn(DataStateTypes.DELETE.getState()),
                        bpDepart1.showState.isNull()));
        predicate = id == null ? predicate : ExpressionUtils.and(predicate, bpDepart1.parentId.eq(id));
        ArrayList<BpDepartListBean> list = new ArrayList<>();
        Page<BpDepart> all = dao.findAll(predicate, page);
        // 未传Id将部门全部显示出来
        if (id == null) {
            for (BpDepart bpDepart : all) {
                BpDepartListBean bpDepartListBean = new BpDepartListBean();
                bpDepartListBean.setId(bpDepart.getId());
                bpDepartListBean.setName(bpDepart.getName());
                bpDepartListBean.setParentId(bpDepart.getParentId());
                bpDepartListBean.setCode(bpDepart.getCode());
                bpDepartListBean.setType(bpDepart.getType());
                if (bpDepart.getChiefId() != null) {
                    bpDepartListBean.setChiefName(baseUserDao.getBaseUserNameById(bpDepart.getChiefId()));
                    bpDepartListBean.setChiefId(bpDepart.getChiefId());
                }
                bpDepartListBean.setRemark(bpDepart.getRemark());
                list.add(bpDepartListBean);
            }
            return new PageImpl<>(list, page, all.getTotalElements());
        }
        // 根据上级Id查询
        for (BpDepart bpDepart : all) {
            BpDepartListBean bpDepartListBean = new BpDepartListBean();
            bpDepartListBean.setId(bpDepart.getId());
            bpDepartListBean.setName(bpDepart.getName());
            bpDepartListBean.setParentId(bpDepart.getParentId());
            bpDepartListBean.setCode(bpDepart.getCode());
            bpDepartListBean.setType(bpDepart.getType());
            if (bpDepart.getChiefId() != null) {
                bpDepartListBean.setChiefName(baseUserDao.getBaseUserNameById(bpDepart.getChiefId()));
                bpDepartListBean.setChiefId(bpDepart.getChiefId());
            }
            bpDepartListBean.setRemark(bpDepart.getRemark());
            list.add(bpDepartListBean);
            // 查询子部门
            List<BpDepartListBean> findget = findget(bpDepart.getId());
            // bpDepartListBean.setBpDepartListBeans(findget);
            list.addAll(findget);

        }
        return new PageImpl<>(list, page, all.getTotalElements());
    }

    private List<BpDepartListBean> findget(Long id) {
        QBpDepart bpDepart1 = QBpDepart.bpDepart1;
        Predicate predicate = bpDepart1.isNotNull();
        predicate = id == null ? predicate : ExpressionUtils.and(predicate, bpDepart1.parentId.eq(id));
        predicate = ExpressionUtils.and(predicate,
                ExpressionUtils.or(bpDepart1.showState.notIn(DataStateTypes.DELETE.getState()),
                        bpDepart1.showState.isNull()));
        ArrayList<BpDepartListBean> list = new ArrayList<>();
        Iterable<BpDepart> all = dao.findAll(predicate);
        for (BpDepart bpDepart : all) {
            BpDepartListBean bpDepartListBean = new BpDepartListBean();
            bpDepartListBean.setId(bpDepart.getId());
            bpDepartListBean.setName(bpDepart.getName());
            bpDepartListBean.setParentId(bpDepart.getParentId());
            bpDepartListBean.setCode(bpDepart.getCode());
            bpDepartListBean.setType(bpDepart.getType());
            if (bpDepart.getChiefId() != null) {
                bpDepartListBean.setChiefName(baseUserDao.getBaseUserNameById(bpDepart.getChiefId()));
                bpDepartListBean.setChiefId(bpDepart.getChiefId());
            }
            bpDepartListBean.setRemark(bpDepart.getRemark());
            list.add(bpDepartListBean);
            // 进行循环查询子部门，直到没有时跳出循环
            List<BpDepartListBean> findget = findget(bpDepart.getId());
            list.addAll(findget);
        }
        return list;

    }

    @Override
    public DpDepartUserBean getUser() {
        List<BpDepart> all = dao.findAll();
        ArrayList<DpDepartUserBean> list = new ArrayList<>();
        Map<Long, DpDepartUserBean> map = new HashMap<>();
        for (BpDepart d : all) {
            DpDepartUserBean bpDepartBean = new DpDepartUserBean();
            bpDepartBean.setId(d.getId());
            bpDepartBean.setParentId(d.getParentId());
            bpDepartBean.setParentName(d.getName());
            if (d.getChiefId() != null) {
                try {
                    Optional<BaseUser> obu = baseUserDao.findById(d.getChiefId());
                    if (obu.isPresent()) {
                        BaseUser one = obu.get();
                        bpDepartBean.setUserName(baseUserDao.getBaseUserNameById(one.getId()));
                        bpDepartBean.setUserId(one.getId());
                        if (one.getJob() != null) {
                            BpJob one1 = jobDao.getOne(one.getJob());
                            bpDepartBean.setJobName(one1.getName());
                        }
                    }
                } catch (Exception e) {
                    log.error("get user error", e);
                    e.printStackTrace();
                }
            }
            map.put(d.getId(), bpDepartBean);
            list.add(bpDepartBean);
        }
        for (DpDepartUserBean d : list) {
            DpDepartUserBean parent = map.get(d.getParentId());
            if (parent != null) {
                parent.getDpDepartUserBeanList().add(d);
            }
        }
        return list.size() > 0 ? findTop2(list.get(0), map) : null;
    }

    private DpDepartUserBean findTop2(DpDepartUserBean bpDepartBean, Map<Long, DpDepartUserBean> map) {
        while (bpDepartBean.getParentId() != null) {
            bpDepartBean = map.get(bpDepartBean.getParentId());
        }
        return bpDepartBean;
    }

    @Override
    public Page<SimpleInfoBean> findByPageSimple(Pageable page, SearchDepartBean condition) {
        Predicate p = prepareSearchConditon(condition, null);
        Page<BpDepart> data = p == null ? dao.findAll(page) : dao.findAll(p, page);
        return PageDataUtils.convertPageData(data, new PageDataConvert<SimpleInfoBean, BpDepart>() {

            @Override
            public SimpleInfoBean convert(BpDepart f) {
                SimpleInfoBean bean = new SimpleInfoBean();
                bean.setName(f.getName());
                bean.setId(f.getId());
                bean.setCode(f.getCode());
                return bean;
            }
        });
    }


    //获取部门负责人信息
    @Override
    public ResultBean getDepartDutyUser(Long departId) {
        BaseDepartDutyUserBean userBean = null;
        if (departId != null) {
            Optional<BpDepart> bpDepart = dao.findById(departId);
            if (bpDepart.isPresent()) {
                userBean = new BaseDepartDutyUserBean();
                userBean.setDepartId(bpDepart.get().getId());
                userBean.setDepartName(bpDepart.get().getName());
                userBean.setId(bpDepart.get().getChiefId());
                if (userBean.getId() != null) {
                    String chiefUserName = baseUserDao.getRealNameById(userBean.getId());
                    userBean.setRealName(chiefUserName);
                }
            }
        }
        return ResultBean.success(userBean);
    }

    @Override
    public List<BpDepart> findAllDepartByTenentId(Long tenentId) {
        return dao.findAllDepartByTenentId(tenentId);
    }

    @Override
    public ResultBean getDepartByUserId(Long userId) {
        BaseUser user = baseUserDao.getOne(userId);
        if (user == null) {
            return ResultBean.success(null);
        }
        Long departId = user.getDepartId();
        return ResultBean.success(dao.getOne(departId));
    }

    @Override
    public ResultBean getNDepartDutyUser(DepartDutyUserBean bean) {
        Long departId = bean.getDepartId();
        Long userId = bean.getUserId();
        Integer level = bean.getLevel();
        Assert.isTrue(level >= 0, "level must >= 0");
        if (departId == null) {
            Assert.notNull(userId, "部门和人员至少传一个");
            departId = baseUserDao.findById(userId).map(r -> r.getDepartId()).orElseThrow(() -> new IllegalArgumentException("此人员不存在"));
        }
        if (level != 0) {
            for (int i = 1; i <= level; i++) {
                Assert.notNull(departId, "请输入正确的级别");
                departId = dao.findParentIdById(departId);
            }
        }
        Long chiefId = dao.findChiefIdById(departId);
        if (chiefId != null) {
            BaseUser user = baseUserDao.getOne(chiefId);
            user.setBaseLoginAccount(null);
            return ResultBean.success(user);
        }
        return ResultBean.fail(101, "此部门不存在负责人");
    }

    /**
     * 获取部门下拉列表
     *
     * @return
     */
    @Override
    public List<SimpleSelectListBean> getList() {
        List<SimpleSelectListBean> list = new ArrayList<>();
        List<BpDepart> departs = dao.findAll();
        for (BpDepart depart : departs) {
            SimpleSelectListBean bean = new SimpleSelectListBean();
            bean.setValue(depart.getId());
            bean.setLabel(depart.getName());
            list.add(bean);
        }
        return list;
    }

    /**
     * 获取部门树形结构
     *
     * @return
     */
    @Override
    public List<BpDepartTreeBean> getDepartList() {
        List<BpDepart> all = dao.findAll();
        List<BpDepartTreeBean> list = all.stream().map(r -> {
            BpDepartTreeBean bean = new BpDepartTreeBean();
            BeanUtils.copyProperties(r, bean);
            return bean;
        }).collect(Collectors.toList());
        Map<Long, BpDepartTreeBean> map = list.stream().collect(Collectors.toMap(BpDepartTreeBean::getId, r -> r));
        List<BpDepartTreeBean> returnList = new ArrayList<>();
        for (BpDepartTreeBean listBean : list) {
            Long parentId = listBean.getParentId();
            if (parentId != null) {
                BpDepartTreeBean bean = map.get(parentId);
                if (bean != null) {
                    List<BpDepartTreeBean> childrenList = bean.getChildrenList();
                    childrenList = childrenList == null ? Lists.newArrayList() : childrenList;
                    childrenList.add(listBean);
                    bean.setChildrenList(childrenList);
                }
            }
        }
        if (!CollectionUtils.isEmpty(list)) {
            for (BpDepartTreeBean b : list) {
                if (b.getParentId() == null) {
                    returnList.add(b);
                }
            }
        }
        return returnList;
    }

    /**
     * 获取父部门下一级子部门
     *
     * @param page
     * @param bean
     * @return
     */
    @Override
    public Page<BpDepartListBean> getListByParentId(Pageable page, BpDepartSearchBean bean) {
        QBpDepart q = QBpDepart.bpDepart1;
        Predicate predicate = q.isNotNull();
        predicate = ExpressionUtils.and(predicate,
                ExpressionUtils.or(q.showState.notIn(DataStateTypes.DELETE.getState()),
                        q.showState.isNull()));
        if (bean.getNameOrCode() != null) {
            predicate = ExpressionUtils.and(predicate, ExpressionUtils.or(q.name.contains(bean.getNameOrCode()),
                    q.code.like("%" + bean.getNameOrCode() + "%")));
        }
        if (bean.getChiefId() != null) {
            predicate = ExpressionUtils.and(predicate, q.chiefId.eq(bean.getChiefId()));
        }
        if (bean.getLocateSync() != null) {
            predicate = ExpressionUtils.and(predicate, q.locateSync.eq(bean.getLocateSync()));
        }
        Long id = bean.getId();
        predicate = buildSearchSubdepartCondition(id, predicate, q, dao);
        Page<BpDepart> all = dao.findAll(predicate, page);
        return PageDataUtils.convertPageData(all, new PageDataUtils.PageDataConvert<BpDepartListBean, BpDepart>() {
            @Override
            public BpDepartListBean convert(BpDepart depart) {
                BpDepartListBean bean = new BpDepartListBean();
                BeanUtils.copyProperties(depart, bean);
                if (depart.getChiefId() != null) {
                    bean.setChiefName(baseUserDao.getBaseUserNameById(depart.getChiefId()));
                    bean.setChiefId(depart.getChiefId());
                }
                return bean;
            }
        });
    }

    public static Predicate buildSearchSubdepartCondition(Long id, Predicate predicate, QBpDepart q, BpDepartDao dao) {
        String code = null;
        if (id == null) {
            BpDepart fatherDepart = dao.getFatherDepart(Context.getCompanyCode(), Context.getCurrentTenantId());
            if (fatherDepart != null) {
                code = fatherDepart.getCode();
                id = fatherDepart.getId();
            }
        } else {
            Optional<BpDepart> obd = dao.findById(id);
            if (obd.isPresent()) {
                code = obd.get().getCode();
            }
        }
        predicate = ExpressionUtils.and(predicate, q.code.like(code + "%"));
        predicate = ExpressionUtils.and(predicate, q.id.notIn(id));
        return predicate;
    }

    @Override
    public List<SimpleSelectListBean> getDeptPmsList() {
        List<SimpleSelectListBean> list = new ArrayList<>();
        List<BpDepart> departs = getCurUserPmsDept();
        for (BpDepart depart : departs) {
            SimpleSelectListBean bean = new SimpleSelectListBean();
            bean.setValue(depart.getId());
            bean.setLabel(depart.getName());
            list.add(bean);
        }
        return list;
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @Override
    public List<String> deleteByIds(List<Long> ids) throws ApiBusinessException {
        List<String> message = new ArrayList<>();
        if (CollectionUtils.isEmpty(ids)) {
            throw new IllegalArgumentException("请选择要删除的部门");
        }
        //排序 先将子级部门删除
        Collections.sort(ids);
        Collections.reverse(ids);
        // 删除失败的部门数据
        List<DepartDeleteCheckVO> list = Lists.newArrayList();
        for (Long id : ids) {
            try {
                delete(id);
            } catch (ApiBusinessException e) {
                if (e.getCode() == Status.DELETE_CHECK_FAILED.getCode() && StringUtils.isNotEmpty(e.getMessage())) {
                    DepartDeleteCheckVO vo = JSONObject.parseObject(e.getMessage(), DepartDeleteCheckVO.class);
                    list.add(vo);
                }
            } catch (IllegalArgumentException e) {
                log.error(e.getMessage(), e);
                message.add(e.getMessage());
            } catch (Exception ex) {
                log.error(ex.getMessage(), ex);
            }
        }
        if (!CollectionUtils.isEmpty(list)) {
            throw new ApiBusinessException(Status.DELETE_CHECK_FAILED.getCode(), JSONObject.toJSONString(list));
        }
        return message;
    }

    public List<BpDepart> getCurUserPmsDept() {
        List<Long> deptIds = dataAuthService.findDepartIdsByCurUser();
        return dao.findByIdIn(deptIds);
    }

    @Override
    public Page<SimpleInfoBean> getDeptPmsList(Pageable page, SearchDepartBean condition) {
        List<Long> deptIds = dataAuthService.findDepartIdsByCurUser();
        Page<BpDepart> data;
        if (!CollectionUtils.isEmpty(deptIds)) {
            Predicate predicate = prepareSearchConditon(condition, deptIds);
            data = predicate == null ? dao.findAll(page) : dao.findAll(predicate, page);
        } else {
            List<BpDepart> resultList = Lists.newArrayList();
            data = new PageImpl<>(resultList, page, 0);
        }
        return PageDataUtils.convertPageData(data, f -> {
            SimpleInfoBean bean = new SimpleInfoBean();
            bean.setName(f.getName());
            bean.setId(f.getId());
            bean.setCode(f.getCode());
            return bean;
        });
    }

    public BpDepart getFatherDepart(Long tenentId, String orgCode){
        return dao.getFatherDepart(orgCode, tenentId);
    }

    @Override
    public List<ApiDepartDto> findListByChiefId(Long chiefId, Long tenentId, String orgCode) {
        return departMapper.findListByChiefId(chiefId, tenentId, orgCode);
    }

    @Override
    public List<ApiDepartDto> getListForApi(String departName, String departCode, Long tenentId, String orgCode) {
        return departMapper.getListForApi(departName, departCode, tenentId, orgCode);
    }

    @Override
    public com.baomidou.mybatisplus.extension.plugins.pagination.Page<ApiDepartDto> getListByPageForApi(Integer page, Integer size, String departName, String departCode, Long tenentId, String orgCode) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page pageForApi = new com.baomidou.mybatisplus.extension.plugins.pagination.Page(page+1, size);
        return departMapper.getListByPageForApi(pageForApi, departName, departCode, tenentId, orgCode);
    }

    @Override
    public Map<Long, BpDepart> getDepartMapByIds(List<Long> ids) {
        Map<Long, BpDepart> map = new HashMap<>();
        if (CollectionUtils.isEmpty(ids)) {
            return map;
        }
        List<BpDepart> departList = dao.findByIdIn(ids);
        if (!CollectionUtils.isEmpty(departList)) {
            map = departList.stream().collect(Collectors.toMap(BpDepart::getId, e -> e));
        }
        return map;
    }
}
